#!/bin/bash

#
# This file is distributed under the MIT License. See LICENSE.md for details.
#

SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

INPUT=""
OPTIMIZE=0
SKIP=0
ISOLATE=0
SUPPORT_CONFIG=normal
EXTRA_OPTIONS=""

set -e
set -o pipefail

while [[ $# > 0 ]]
do
    key="$1"
    case $key in
        -O0)
            OPTIMIZE="0"
            shift
            ;;
        -O1)
            OPTIMIZE="1"
            shift # past argument
            ;;
        -O2)
            OPTIMIZE="2"
            shift # past argument
            ;;
        -trace)
            SUPPORT_CONFIG="trace"
            shift # past argument
            ;;
        -s)
            SKIP="1"
            shift # past argument
            ;;
        -i)
            ISOLATE="1"
            shift # past argument
            ;;
        --)
            shift
            break
            ;;
        *)
            # unknown option
            if [ -z "$INPUT" ]; then
                INPUT="$key"
            else
                break;
            fi
            shift
            ;;
    esac
done

# Output file name
LL="$INPUT"
LIBSCSV="$LL.ll.need.csv"

# Required programs
export PATH="$SCRIPT_PATH:$PATH"
CC="${CC:-cc}"
LINK="llvm-link"
LLC="llc"
OPT="opt"
REVAMB="revamb"
REVAMBDUMP="revamb-dump"
TOOPT="csv-to-ld-options"

# Read endianess and architecture bytes
ARCHID=$(python -c '
from binascii import hexlify
import sys
file = open(sys.argv[1], "rb")
file.seek(5)
result = hexlify(file.read(1))
file.seek(18)
result += hexlify(file.read(2))
file.close()
print(result.decode("utf-8"))' "$INPUT")

case "$ARCHID" in
    012800)
        ARCH=arm;
        ;;
    020008)
        ARCH=mips;
        ;;
    013e00)
        ARCH=x86_64;
        ;;
    010300)
        ARCH=i386;
        ;;
    *)
        echo "Unknown architecture: $ARCHID"
        exit 1
        ;;
esac

SUPPORT_NAME="support-$ARCH-$SUPPORT_CONFIG.ll"
SUPPORT_PATH="$SCRIPT_PATH/../share/revamb/$SUPPORT_NAME"

if [ '!' -e "$SUPPORT_PATH" ]; then
    SUPPORT_PATH="$SCRIPT_PATH/$SUPPORT_NAME"
    if [ '!' -e "$SUPPORT_PATH" ]; then
        echo "Can't find $SUPPORT_NAME"
        exit 1
    fi
fi

if [ "$ISOLATE" -eq 1 ]; then
    EXTRA_OPTIONS="$EXTRA_OPTIONS --functions-boundaries"
fi

if [ "$SKIP" -eq 0 ]; then
    REVAMB_LOG="$LL.log"
    CSV="$LL.ll.li.csv"
    "$REVAMB" -g ll --debug jtcount,osrjts --use-sections $EXTRA_OPTIONS "$INPUT" "$LL.ll" "$@" |& tee "$REVAMB_LOG"
fi

if [ "$ISOLATE" -eq 1 ]; then
    LL_ISOLATED="$LL.isolated"
    "$REVAMBDUMP" -i "$LL_ISOLATED.ll" "$LL.ll"
    LL="$LL_ISOLATED"
fi

LL_LINKED="$LL.linked"
"$LINK" "$LL.ll" "$SUPPORT_PATH" -o "$LL_LINKED.ll" -S
LL="$LL_LINKED"

OUTPUT="$INPUT.translated"
if [ "$OPTIMIZE" -eq 0 ]; then
    "$LLC" -O0 -filetype=obj "$LL.ll" -o "$OBJ"
elif [ "$OPTIMIZE" -eq 1 ]; then
    "$LLC" -O2 -filetype=obj "$LL.ll" -o "$OBJ" -regalloc=fast -disable-machine-licm
elif [ "$OPTIMIZE" -eq 2 ]; then
    LL_OPT="$LL.opt"
    "$OPT" -O2 -S "$LL.ll" -o "$LL_OPT.ll"
    "$LLC" -O2 -filetype=obj "$LL_OPT.ll" -o "$OBJ" -regalloc=fast -disable-machine-licm
    LL="$LL_OPT"
fi

if "$CC" -no-pie |& grep 'unrecognized command line option'; then
    DISABLE_PIE="-fno-pie"
else
    DISABLE_PIE="-fno-pie -no-pie"
fi

OBJ="$LL.o"
"$CC" \
      "$OBJ" \
      -lz -lm -lrt $("$TOOPT" "$CSV" "$LIBSCSV") -L ./ \
      -o "$OUTPUT" \
      $DISABLE_PIE

UNPATCHED_OUTPUT="$OUTPUT.tmp"
mv "$OUTPUT" "$UNPATCHED_OUTPUT"
merge-dynamic.py "$UNPATCHED_OUTPUT" "$INPUT" "$OUTPUT"
rm "$UNPATCHED_OUTPUT"
